package ar.unc.famaf.pln.giveselector.classifier;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import ar.unc.famaf.pln.giveselector.context.Response;

/**
 * Saves the information of the DF's reaction to an specific 
 * occurrence of an Utterance.
 * 
 * @author David Racca (david.racca@gmail.com)
 * 
 *
 */
@SuppressWarnings({ "serial", "rawtypes" })
public class Occurrence implements Serializable, Comparable
{
	private final UtteranceP owner;			// The owner of this Occurrence
	private final Integer gameId;			// The Game ID where this instruction occurred
	private final Date timestamp;			// The Date time where this instruction occurred
	private Response reaction;				// How the DF reacted in response to this instruction occurrence
											// or in response to another related utterance
	private List<Occurrence> related;		// List of occurrences that are related to this occurrence


	public Occurrence(UtteranceP owner, Integer gameId, Date timestamp, Response reaction)
	{
		this.owner = owner;
		this.gameId = gameId;
		this.timestamp = timestamp;
		this.reaction = reaction;
		this.related = new ArrayList<Occurrence>();
	}


	/**
	 * @return The UtteranceP object which this occurrence belongs to
	 */
	public UtteranceP getOwner()
	{
		return owner;
	}


	/**
	 * @return The GIVE log Game id number where this occurrence
	 * occurred.
	 */
	public Integer getGameId()
	{
		return gameId;
	}


	/** 
	 * @return The GIVE log time stamp information that identifies
	 * when this occurrence occurred.
	 */
	public Date getTimestamp()
	{
		return timestamp;
	}


	/** 
	 * @return The DF's reaction that represents how the DF has reacted
	 * to this specific occurrence.
	 */
	public Response getResponse()
	{
		return reaction;
	}


	/**
	 * Adds the given occurrence to the list of related Occurrences. 
	 * @param occurrence
	 */
	public void addRelatedOccurrence(Occurrence occurrence)
	{
		related.add(occurrence);
	}


	/**
	 * Adds a copy of all the given occurrences collection.
	 */
	public void addRelatedOccurences(Collection<Occurrence> occurrences)
	{
		related.addAll(occurrences);
	}


	/**
	 * @return True if there are more than one associated occurrences
	 */
	public boolean hasRelatedOccurrences()
	{
		return related.size()>1;
	}


	/**
	 * @return The list of occurrences that are related to this occurrence.
	 */
	public List<Occurrence> getRelatedOccurrences()
	{
		return related;
	}


	/**
	 * Sorts in ascending order by time stamp the related Occurrences list
	 * in such a way that if the first Occurrence object represents a "Success", 
	 * then the rest of the objects share this "Successness".
	 */
	@SuppressWarnings("unchecked")
	public void sortRelatedOccurrences()
	{
		Collections.sort(related);
	}


	/**
	 * Occurrence comparator by chronological order by comparing the 
	 * time stamp attribute.
	 */
	@Override
	public int compareTo(Object arg0) {
		int result = 0;
		if (arg0 instanceof Occurrence)
		{
			Occurrence p = (Occurrence) arg0; 
			Date d1 = timestamp;
			Date d2 = p.getTimestamp();
			result = ( (d1.after(d2)) ? 1 : ( (d1 == d2) ? 0 : -1));
		}
		return result;
	}


	/**
	 * @return a string representation for this object
	 */
	public String toString()
	{
		return "Occurrence = [GameId: " + gameId + ", TimeStamp: " + timestamp + "]"; 
	}

}